package com.zp.business.impl.patient;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zp.business.entity.patient.ClinicMaster;
import com.zp.business.entity.patient.bo.ClinicMasterBo;
import com.zp.business.entity.patient.bo.PatMasterIndexBo;
import com.zp.business.entity.patient.vo.ClinicMasterVo;
import com.zp.business.mapper.patient.ClinicMasterMapper;
import com.zp.business.service.patient.IClinicMasterService;
import com.zp.business.service.patient.IPatMasterIndexService;
import com.zp.common.core.constant.CacheNames;
import com.zp.common.core.constant.UserConstants;
import com.zp.common.core.utils.StringUtils;
import com.zp.common.myBatis.core.page.PageQuery;
import com.zp.common.myBatis.core.page.TableDataInfo;
import com.zp.common.redis.utils.CacheUtils;
import com.zp.common.satoken.utils.LoginHelper;
import com.zp.system.api.entity.SysDept;
import com.zp.system.api.entity.SysUser;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 门诊就诊记录-clinic_masterService业务层处理
 *
 * @author zhang peng
 * @ date 2023-12-26
 */
@RequiredArgsConstructor
@Service
//@DS("slave")
public class ClinicMasterServiceImpl implements IClinicMasterService {

    private final ClinicMasterMapper baseMapper;
    private final IPatMasterIndexService patMasterIndexService;


    /**
     * 用户信息
     */
    static Map<String, SysUser> sysUserMap = CacheUtils.get(CacheNames.SYS_USER);

    static Map<String, SysDept> sysDeptMap = CacheUtils.get(CacheNames.SYS_DEPT);


    /**
     * 查询门诊就诊记录-clinic_master
     */
    @Override
    public ClinicMasterVo queryById (String id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询门诊就诊记录-clinic_master列表(分页)
     */
    @Override
    public TableDataInfo<ClinicMasterVo> queryPageList (ClinicMasterBo bo, PageQuery pageQuery) {
        Page<ClinicMasterVo> result = new Page<>();
//        Map<String, SysDept> sysDeptMap = CacheTEntity.getCacheMap(new SysDept(),CacheNames.SYS_DEPT);
        if (StringUtils.equals(bo.getApiSource(), "2")) {
            // 门诊收费页面查询
            result = baseMapper.selectVoPageInClinicOrder(pageQuery.build(), bo);
        } else {
            LambdaQueryWrapper<ClinicMaster> lqw = buildQueryWrapper(bo);
            lqw.orderByAsc(ClinicMaster::getVisitNo);
            // 挂号页面查询
            result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        }

        result.getRecords().forEach(item -> {
            item.setDeptName(CollectionUtils.isNotEmpty(sysDeptMap) && StringUtils.isNotEmpty(item.getDeptId())
                    ? sysDeptMap.get(item.getDeptId()).getDeptName() : "");
            item.setDoctorName(CollectionUtils.isNotEmpty(sysUserMap) && StringUtils.isNotBlank(item.getDoctorId())
                    ? sysUserMap.get(item.getDoctorId()).getNickName() : "");
        });
        return TableDataInfo.build(result);
    }

    @Override
    public Map<String, Integer> getPatientCount (ClinicMasterBo bo) {
        bo.setClinicType("");
        Map<String, Integer> numGroupClinicType = getNumGroupClinicType(bo);
        LambdaQueryWrapper<ClinicMaster> lqw = buildQueryWrapper(bo);
        Long totality = baseMapper.selectCount(lqw);
        numGroupClinicType.put("totality", Math.toIntExact(totality));
        return numGroupClinicType;
    }

    /**
     * 查询门诊就诊记录-clinic_master列表(不分页)
     */
    @Override
    public List<ClinicMasterVo> queryList (ClinicMasterBo bo) {
        LambdaQueryWrapper<ClinicMaster> lqw = buildQueryWrapper(bo);
        lqw.orderByAsc(ClinicMaster::getVisitNo);
        List<ClinicMasterVo> clinicMasterVos = baseMapper.selectVoList(lqw);
        clinicMasterVos.forEach(clinicMasterVo -> {
            clinicMasterVo.setDeptName(ObjectUtil.isNotNull(sysDeptMap.get(clinicMasterVo.getDeptId())) ? sysDeptMap.get(clinicMasterVo.getDeptId()).getDeptName() : "");
            clinicMasterVo.setDoctorName(StringUtils.isNotBlank(clinicMasterVo.getDoctorId()) && ObjectUtil.isNotNull(sysUserMap.get(clinicMasterVo.getDoctorId()))
                    ? sysUserMap.get(clinicMasterVo.getDoctorId()).getNickName() : "");

        });
        return clinicMasterVos;
    }

    private LambdaQueryWrapper<ClinicMaster> buildQueryWrapper (ClinicMasterBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<ClinicMaster> lqw = Wrappers.lambdaQuery();
        lqw.in(CollectionUtil.isNotEmpty(bo.getClinicNos()), ClinicMaster::getClinicNo, bo.getClinicNos());
        lqw.in(CollectionUtil.isNotEmpty(bo.getIds()), ClinicMaster::getId, bo.getIds());
        lqw.and(StringUtils.isNotBlank(bo.getItemInfo()), wrapper -> wrapper.like(ClinicMaster::getName, bo.getItemInfo())
                .or().like(StringUtils.isNotBlank(bo.getItemInfo()), ClinicMaster::getClinicNo, bo.getItemInfo())
                .or().like(StringUtils.isNotBlank(bo.getItemInfo()), ClinicMaster::getInputCode, bo.getItemInfo().toUpperCase()));
        lqw.eq(StringUtils.isNotBlank(bo.getRecordNo()), ClinicMaster::getRecordNo, bo.getRecordNo());
        lqw.eq(StringUtils.isNotBlank(bo.getOrgId()), ClinicMaster::getOrgId, bo.getOrgId());
        lqw.eq(StringUtils.isNotBlank(bo.getRegistType()), ClinicMaster::getRegistType, bo.getRegistType());
        lqw.eq(StringUtils.isNotBlank(bo.getIsEmergency()), ClinicMaster::getIsEmergency, bo.getIsEmergency());
        lqw.eq(StringUtils.isNotBlank(bo.getPatientId()), ClinicMaster::getPatientId, bo.getPatientId());
        lqw.eq(bo.getVisitDate() != null && StringUtils.isEmpty(bo.getItemInfo()), ClinicMaster::getVisitDate, bo.getVisitDate());
        lqw.eq(bo.getVisitNo() != null, ClinicMaster::getVisitNo, bo.getVisitNo());
        lqw.like(StringUtils.isNotBlank(bo.getClinicNo()), ClinicMaster::getClinicNo, bo.getClinicNo());
        lqw.eq(StringUtils.isNotBlank(bo.getRegistId()), ClinicMaster::getRegistId, bo.getRegistId());
        lqw.like(StringUtils.isNotBlank(bo.getName()), ClinicMaster::getName, bo.getName());
        lqw.eq(StringUtils.isNotBlank(bo.getInputCode()), ClinicMaster::getInputCode, bo.getInputCode());
        lqw.eq(StringUtils.isNotBlank(bo.getSex()), ClinicMaster::getSex, bo.getSex());
        lqw.eq(bo.getAge() != null, ClinicMaster::getAge, bo.getAge());
        lqw.eq(bo.getAgeMonth() != null, ClinicMaster::getAgeMonth, bo.getAgeMonth());
        lqw.eq(bo.getAgeDay() != null, ClinicMaster::getAgeDay, bo.getAgeDay());
        lqw.eq(bo.getAgeHours() != null, ClinicMaster::getAgeHours, bo.getAgeHours());
        lqw.eq(bo.getAgeMinutes() != null, ClinicMaster::getAgeMinutes, bo.getAgeMinutes());
        lqw.eq(StringUtils.isNotBlank(bo.getPhone()), ClinicMaster::getPhone, bo.getPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), ClinicMaster::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getAddressCode()), ClinicMaster::getAddressCode, bo.getAddressCode());
        lqw.eq(StringUtils.isNotBlank(bo.getIdNo()), ClinicMaster::getIdNo, bo.getIdNo());
        lqw.like(StringUtils.isNotBlank(bo.getGuardianName()), ClinicMaster::getGuardianName, bo.getGuardianName());
        lqw.eq(StringUtils.isNotBlank(bo.getGuardianPhone()), ClinicMaster::getGuardianPhone, bo.getGuardianPhone());
        lqw.eq(bo.getBirthdayDate() != null, ClinicMaster::getBirthdayDate, bo.getBirthdayDate());
        lqw.eq(StringUtils.isNotBlank(bo.getMarriage()), ClinicMaster::getMarriage, bo.getMarriage());
        lqw.eq(StringUtils.isNotBlank(bo.getWeight()), ClinicMaster::getWeight, bo.getWeight());
        lqw.eq(StringUtils.isNotBlank(bo.getNation()), ClinicMaster::getNation, bo.getNation());
        lqw.eq(StringUtils.isNotBlank(bo.getNationality()), ClinicMaster::getNationality, bo.getNationality());
        lqw.eq(StringUtils.isNotBlank(bo.getNativePlace()), ClinicMaster::getNativePlace, bo.getNativePlace());
        lqw.eq(StringUtils.isNotBlank(bo.getNativePlaceCode()), ClinicMaster::getNativePlaceCode, bo.getNativePlaceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getZipCode()), ClinicMaster::getZipCode, bo.getZipCode());
        lqw.eq(StringUtils.isNotBlank(bo.getHomePlace()), ClinicMaster::getHomePlace, bo.getHomePlace());
        lqw.eq(StringUtils.isNotBlank(bo.getHomePlaceCode()), ClinicMaster::getHomePlaceCode, bo.getHomePlaceCode());
        lqw.eq(StringUtils.isNotBlank(bo.getCountryGroup()), ClinicMaster::getCountryGroup, bo.getCountryGroup());
        lqw.eq(StringUtils.isNotBlank(bo.getContactsRelation()), ClinicMaster::getContactsRelation, bo.getContactsRelation());
        lqw.eq(StringUtils.isNotBlank(bo.getContacts()), ClinicMaster::getContacts, bo.getContacts());
        lqw.eq(StringUtils.isNotBlank(bo.getContactsIdNo()), ClinicMaster::getContactsIdNo, bo.getContactsIdNo());
        lqw.eq(StringUtils.isNotBlank(bo.getContactsAddress()), ClinicMaster::getContactsAddress, bo.getContactsAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getContactsPhone()), ClinicMaster::getContactsPhone, bo.getContactsPhone());
        lqw.eq(StringUtils.isNotBlank(bo.getIdentity()), ClinicMaster::getIdentity, bo.getIdentity());
        lqw.eq(StringUtils.isNotBlank(bo.getEduLevel()), ClinicMaster::getEduLevel, bo.getEduLevel());
        lqw.eq(StringUtils.isNotBlank(bo.getChargeType()), ClinicMaster::getChargeType, bo.getChargeType());
        lqw.eq(StringUtils.isNotBlank(bo.getInsuranceType()), ClinicMaster::getInsuranceType, bo.getInsuranceType());
        lqw.eq(StringUtils.isNotBlank(bo.getSource()), ClinicMaster::getSource, bo.getSource());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicSource()), ClinicMaster::getClinicSource, bo.getClinicSource());
        lqw.eq(StringUtils.isNotBlank(bo.getFirstVisitIndicator()), ClinicMaster::getFirstVisitIndicator, bo.getFirstVisitIndicator());
        lqw.eq(StringUtils.isNotBlank(bo.getInsuranceNo()), ClinicMaster::getInsuranceNo, bo.getInsuranceNo());
        lqw.eq(StringUtils.isNotBlank(bo.getResidenceNo()), ClinicMaster::getResidenceNo, bo.getResidenceNo());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitInContract()), ClinicMaster::getUnitInContract, bo.getUnitInContract());
        lqw.eq(StringUtils.isNotBlank(bo.getUnitEin()), ClinicMaster::getUnitEin, bo.getUnitEin());
        lqw.eq(StringUtils.isNotBlank(bo.getDeptId()), ClinicMaster::getDeptId, bo.getDeptId());
        lqw.eq(StringUtils.isNotBlank(bo.getDoctorId()), ClinicMaster::getDoctorId, bo.getDoctorId());
        lqw.eq(StringUtils.isNotBlank(bo.getClinicType()), ClinicMaster::getClinicType, bo.getClinicType());
        lqw.eq(bo.getClinicChage() != null, ClinicMaster::getClinicChage, bo.getClinicChage());
        lqw.eq(bo.getRegistDate() != null, ClinicMaster::getRegistDate, bo.getRegistDate());
        lqw.eq(StringUtils.isNotBlank(bo.getRegistOperator()), ClinicMaster::getRegistOperator, bo.getRegistOperator());
        lqw.eq(StringUtils.isNotBlank(bo.getRegistNo()), ClinicMaster::getRegistNo, bo.getRegistNo());
        lqw.eq(bo.getAcctDateTime() != null, ClinicMaster::getAcctDateTime, bo.getAcctDateTime());
        lqw.eq(bo.getReferralNum() != null, ClinicMaster::getReferralNum, bo.getReferralNum());
        lqw.eq(StringUtils.isNotBlank(bo.getAcctNo()), ClinicMaster::getAcctNo, bo.getAcctNo());
        lqw.eq(StringUtils.isNotBlank(bo.getRemarks()), ClinicMaster::getRemarks, bo.getRemarks());
        lqw.eq(StringUtils.isNotBlank(bo.getIsPhy()), ClinicMaster::getIsPhy, bo.getIsPhy());
        lqw.eq(StringUtils.isNotBlank(bo.getTripCode()), ClinicMaster::getTripCode, bo.getTripCode());
        lqw.eq(StringUtils.isNotBlank(bo.getHealthyCode()), ClinicMaster::getHealthyCode, bo.getHealthyCode());
        lqw.eq(StringUtils.isNotBlank(bo.getFlag()), ClinicMaster::getFlag, bo.getFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getChargeFlag()), ClinicMaster::getChargeFlag, bo.getChargeFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getUnattendedDoctor()), ClinicMaster::getUnattendedDoctor, bo.getUnattendedDoctor());
        lqw.eq(StringUtils.isNotBlank(bo.getRegisterFlag()), ClinicMaster::getRegisterFlag, bo.getRegisterFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getSerialNo()), ClinicMaster::getSerialNo, bo.getSerialNo());
        lqw.eq(StringUtils.isNotBlank(bo.getReadFlag()), ClinicMaster::getReadFlag, bo.getReadFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getPtPayId()), ClinicMaster::getPtPayId, bo.getPtPayId());
        lqw.eq(StringUtils.isNotBlank(bo.getOtpErReflFlag()), ClinicMaster::getOtpErReflFlag, bo.getOtpErReflFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getMdtrtGrpType()), ClinicMaster::getMdtrtGrpType, bo.getMdtrtGrpType());
        lqw.eq(StringUtils.isNotBlank(bo.getTrumFlag()), ClinicMaster::getTrumFlag, bo.getTrumFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getRelTtpFlag()), ClinicMaster::getRelTtpFlag, bo.getRelTtpFlag());
        return lqw;
    }

    @Override
    public Map<String, Integer> getNumGroupClinicType (ClinicMasterBo bo) {
        Map<String, Integer> map = new HashMap<>();
//        LambdaQueryWrapper<ClinicMaster> lqw = Wrappers.lambdaQuery();
//        lqw.eq(ClinicMaster::getOrgId, bo.getOrgId());
//        lqw.eq(ClinicMaster::getVisitDate, bo.getVisitDate());
//        lqw.groupBy(ClinicMaster::getClinicType);
        if (StringUtils.isNotBlank(bo.getItemInfo())) {
            bo.setVisitDate(null);
        }
        List<ClinicMasterVo> clinicMasterVos = baseMapper.getNumGroupClinicType(bo);
        if (CollectionUtils.isEmpty(clinicMasterVos)) {
            map.put("waitDiagnosed", 0);
            map.put("diagnosed", 0);
            map.put("undiagnosed", 0);
        }
        clinicMasterVos.forEach(item -> {
            String key = "waitDiagnosed";
            if (StringUtils.equals(item.getClinicType(), "2")) {
                key = "diagnosed";
            } else if (StringUtils.equals(item.getClinicType(), "3")) {
                key = "undiagnosed";

            }
            map.put(key, item.getPatientNum() == null ? 0 : item.getPatientNum());
        });
        return map;
    }

    /**
     * 新增门诊就诊记录-clinic_master
     */
    @Override
    @Transactional
    public Boolean insertByBo (ClinicMasterBo bo) {
        return ObjectUtil.isNotNull(saveClinicMaster(bo));
    }

    /**
     * 新增门诊就诊记录
     *
     * @param bo
     * @return clinicMaster对象
     */
    @Override
    @Transactional
    public ClinicMaster insertByBoRetCM (ClinicMasterBo bo) {
        return saveClinicMaster(bo);
    }

    public ClinicMaster saveClinicMaster (ClinicMasterBo bo) {
        ClinicMaster add = BeanUtil.toBean(bo, ClinicMaster.class);
        add.setDelFlag("0");
        validEntityBeforeSave(add);
        add.initEntity();
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return add;
    }


    /**
     * 修改门诊就诊记录-clinic_master
     */
    @Override
    public Boolean updateByBo (ClinicMasterBo bo) {
        boolean type = false;
        // 需要修改接诊医生doctor_id
        if (StringUtils.isEmpty(bo.getDoctorId()) && StringUtils.equals(bo.getIsUpdateDoctorId(), UserConstants.YES)) {
            bo.setDoctorId(LoginHelper.getUserId());
        }
        ClinicMaster update = BeanUtil.toBean(bo, ClinicMaster.class);
        validEntityBeforeSave(update);
        int i = baseMapper.updateById(update);
        if (i > 0) {
            PatMasterIndexBo patMasterIndexBo = BeanUtil.toBean(update, PatMasterIndexBo.class);
            patMasterIndexBo.setId(bo.getPatientId());
            patMasterIndexService.updateByBo(patMasterIndexBo);
            bo.setClinicType("2");
            type = updateClinicType(bo);
        }
        return type;
    }

    /**
     * 修改ClinicType
     *
     * @param bo
     * @return
     */
    @Override
    public boolean updateClinicType (ClinicMasterBo bo) {
//        bo.setClinicType("2");
        return baseMapper.updateClinicType(bo) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave (ClinicMaster entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除门诊就诊记录-clinic_master
     */
    @Override
    public Boolean deleteWithValidByIds (Collection<String> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 修改接诊医生doctor_id
     *
     * @return
     */
    @Override
    public boolean updateDoctorId (String clinicId, String isUpdateDoctorId) {
        // 需要修改接诊医生doctor_id
        ClinicMasterVo vo = baseMapper.selectVoById(clinicId);
        if (StringUtils.isEmpty(vo.getDoctorId()) && StringUtils.equals(isUpdateDoctorId, UserConstants.YES)) {
            ClinicMasterBo clinicMasterBo = new ClinicMasterBo();
            clinicMasterBo.setId(vo.getId());
            clinicMasterBo.setDoctorId(LoginHelper.getUserId());
            baseMapper.updateDoctorId(clinicMasterBo);
        }
        return true;
    }
}
